package com.share.common.utils;

import lombok.extern.slf4j.Slf4j;

import javax.servlet.http.HttpServletRequest;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.UnknownHostException;
import java.util.Enumeration;

@Slf4j
public class IpUtil {

    /**
     * 获取用户真实IP地址，不使用request.getRemoteAddr()的原因是有可能用户使用了代理软件方式避免真实IP地址,
     * 如果通过了多级反向代理的话，X-Forwarded-For的值并不止一个,而是一串IP值,取X-Forwarded-For中第一个非unknown的有效IP字符串即可。
     * 如：X-Forwarded-For：192.168.1.110, 192.168.1.120, 192.168.1.130, 192.168.1.100 用户真实IP为：
     * 192.168.1.110
     *
     *
     * location = /freightByIp{
     *             proxy_pass http://xdx8082.com;
     *             proxy_redirect    off;
     *             proxy_set_header  Host             $host;
     *             proxy_set_header  X-Real-IP        $remote_addr;
     *             proxy_set_header  X-Forwarded-For  $proxy_add_x_forwarded_for;
     * }
     * @param request request对象
     */
    public static String getIpAddress(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }


    /**
     * 获取主机名
     *
     * @return 本地主机名
     */
    public static String getHostName() {
        try {
            return InetAddress.getLocalHost().getHostName();
        } catch (UnknownHostException e) {
        }
        return "未知";
    }


    /**
     * 获取服务ip
     *
     * @return
     */
    public static String getIp() {
        return ip;
    }

    /*默认给个广播*/
    private static String ip = "0.0.0.0";
    private static String[] displayNameArr = {"VMware", "Hyper-V", "Cisco", "Sangfor", "VirtualBox", "virbr", "docker", "flannel", "cali", "br-", "veth"};

    /**
     *         windows环境可以使用下面的方式获取，但是无法排除虚拟网卡
     *
     *         String osName = System.getProperty("os.name");
     *         if (osName.toLowerCase().indexOf("windows") > -1) {
     *             try {
     *                 InetAddress i = InetAddress.getLocalHost();
     *                 ip = i.getHostAddress();
     *                 log.info("windows环境-slf4j获取ip=" + ip);
     *             } catch (UnknownHostException e) {
     *                 log.error("windows环境-slf4j获取ip异常", e);
     *             }
     *         }
     */
    static {
        try {
            boolean bFindIP = false;
            InetAddress ia = null;
            Enumeration<NetworkInterface> netInterfaces = NetworkInterface.getNetworkInterfaces();
            while (netInterfaces.hasMoreElements()) {
                if (bFindIP) {
                    break;
                }

                NetworkInterface ni = netInterfaces.nextElement();

                //判断是否为虚拟网卡
                String displayName = ni.getDisplayName();
                boolean isVirtualDevice = false;
                for (String displayNameKeyword : displayNameArr) {
                    if (displayName.contains(displayNameKeyword)) {
                        isVirtualDevice = true;
                        break;//中断这一层for循环
                    }
                }

                //跳过虚拟网卡
                if (isVirtualDevice) {
                    continue;
                }

                Enumeration<InetAddress> ips = ni.getInetAddresses();
                while (ips.hasMoreElements()) {
                    ia = ips.nextElement();
                    if (ia.isSiteLocalAddress() && !ia.isLoopbackAddress() && ia.getHostAddress().indexOf(":") == -1) {
                        bFindIP = true;
                        break;
                    }
                }
            }
            if (null != ia) {
                ip = ia.getHostAddress();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        /**
         * 新版本springboot启动时无法使用sl4j输出日志(老版本可以),因此这里只能使用System.out.println(msg);
         */
        String msg = String.format("sl4j获取ip=%s,osName=%s", ip, System.getProperty("os.name"));
        System.out.println(msg);
    }
}
